/*
 * @Descripttion: 取消請求
 * @version: 1.0.0
 * @Author: lai_hq@qq.com
 * @Date: 2022-05-06 14:37:21
 * @LastEditors: lai_hq@qq.com
 * @LastEditTime: 2022-08-05 15:31:16
 */

import axios, { AxiosRequestConfig, Canceler } from 'axios'
import qs from 'qs'

export default class CancelToken {
    private static pending: Map<string, Canceler> = new Map()

    private static whiteRequest: string[] = []

    /**
     * 得到该格式的url
     * @param {AxiosRequestConfig} config
     * @returns
     */
    private static getUrl(config: AxiosRequestConfig) {
        const { method, url, data, params } = config
        const requestKey = [url, method, qs.stringify(params), qs.stringify(data)]
        return requestKey.filter((i) => i !== '').join('&')
    }

    /**
     * 添加请求
     * @param {AxiosRequestConfig} config
     */
    public static addPending(config: AxiosRequestConfig) {
        const url = this.getUrl(config)

        console.log('addurl______________', url)
        config.cancelToken = new axios.CancelToken((cancel) => {
            if (!this.pending.has(url)) {
                // console.log("____________addpending",url)
                // 如果 pending 中不存在当前请求，则添加进去
                this.pending.set(url, cancel)
            }
        })
    }

    /**
     * 移除请求
     * @param {AxiosRequestConfig} config
     */
    public static removePending(config: AxiosRequestConfig) {
        const url = this.getUrl(config)
        const method = url.split('&')[0]

        console.log('remurl______________', url, config)

        // console.log('this.pending',this.pending)
        if (this.pending.has(url) && !this.whiteRequest.includes(method)) {
            // console.log("____________remove",url,config)
            // 如果在 pending 中存在当前请求标识，需要取消当前请求，并且移除
            const cancel = this.pending.get(url)
            cancel!(url)
            this.pending.delete(url)
        }
    }

    /**
     * 清空 pending 中的请求（在路由跳转时调用）
     */
    public static clearPending() {
        // eslint-disable-next-line no-restricted-syntax
        for (const [url, cancel] of this.pending) {
            cancel(url)
        }
        this.pending.clear()
    }
}
